use std::error::Error;
use std::fmt;
use actix_web::{
    http::StatusCode, Query, FromRequest,
    dev::Handler, HttpRequest, ResponseError, HttpResponse,
};

pub struct VerboseHandler;

impl VerboseHandler {
    pub fn new() -> Self {
        VerboseHandler
    }
}

impl<S> Handler<S> for VerboseHandler {
    type Result = Result<String, VerboseError>;

    fn handle(&self, req: &HttpRequest<S>) -> Self::Result {
        #[derive(Debug, Serialize, Deserialize)]
        struct DebugFlag {
            debug: i32,
        }

        // Query<T>(T)
        let debug = Query::<DebugFlag>::extract(req);
        let debug = match debug {
            Ok(x) => x.into_inner(),
            Err(_) => DebugFlag {debug: -1},
        };

        match debug.debug {
            0 => Ok(format!("{:?}", req)),
            1 => Err(VerboseError::ErrorTooLong),
            2 => Err(VerboseError::ErrorTooShort),
            _ => Err(VerboseError::ErrorUnknown),
        }
    }
}

//pub trait ResponseError: Fail {
//    fn error_response(&self) -> HttpResponse {
//        HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
//    }
//}

#[derive(Debug)]
pub enum VerboseError {
    ErrorTooLong,
    ErrorTooShort,
    ErrorUnknown,
}

impl ResponseError for VerboseError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::Ok()
            .status(StatusCode::from_u16(401).unwrap())
            .body(format!("{:?}\n{}", self, self))
    }
}

impl Error for VerboseError {

}

impl fmt::Display for VerboseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            VerboseError::ErrorTooLong => write!(f, "Error Too Long"),
            VerboseError::ErrorTooShort => write!(f, "Error Too Short"),
            VerboseError::ErrorUnknown => write!(f, "Unkonwn Error"),
        }
    }
}